import { Component, OnInit, OnDestroy } from '@angular/core';
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
import { NzModalSubject, NzNotificationService } from 'ng-zorro-antd';
import { UserService } from '../../services';
import { ResponseError } from '../../../shared';
import { Subscription } from 'rxjs';

@Component({
  selector: 'ege-reset-password',
  templateUrl: './reset-password.component.html',
  styleUrls: ['./reset-password.component.scss']
})
export class ResetPasswordComponent implements OnInit, OnDestroy {

  loading: boolean = false;
  forms: FormGroup;

  validationMessages = {
    'oldPassword': {
      'required':      '请输入你的旧密码！',
      'pattern':       '您输入旧密码格式不正确！'
    },
    'newPassword': {
      'required':      '请输入你的新密码！',
      'pattern':       '您输入新密码格式不正确！',
      'confirm': '输入的新密码不能与旧密码一致！'
    }
  };

  formErrors = {
    'oldPassword': '',
    'newPassword': ''
  };

  private subscriptions: Subscription[] = [];

  constructor(
    private fb: FormBuilder,
    private modalSubject: NzModalSubject,
    private notification: NzNotificationService,
    private userService: UserService
  ) { }

  ngOnInit() {
    this.createForms();
  }

  ngOnDestroy() {
    for(let i = 0; i < this.subscriptions.length; i++) {
      this.subscriptions[i].unsubscribe();
    }
    this.subscriptions = [];
  }

  submitForm(event: Event): void {
    for (const i in this.forms.controls) {
      this.forms.controls[ i ].markAsDirty();
    }
    this.onValueChanged();
    if(this.forms.valid) {
      this.loading = true;
      const resetPassword = this.userService.resetPassword(this.forms.value)
        .subscribe(
          (result) => this.modalSubject.destroy('onOk'),
          (error: ResponseError) => this.handleError(error)
        );
      this.subscriptions.push(resetPassword);
    }
  }

  updateConfirmValidator(): void {
    /** wait for refresh value */
    Promise.resolve().then(() => this.forms.controls.newPassword.updateValueAndValidity());
  }

  getFormControl(name: string): FormControl {
    return this.forms.get(name) as FormControl;
  }

  cancel(): void {
    this.modalSubject.destroy('onCancel');
  }

  private confirmationValidator = (control: FormControl): { [s: string]: boolean } => {
    if (!control.value) {
      return { required: true };
    } else if (control.value === this.forms.controls.oldPassword.value) {
      return { confirm: true, error: true };
    }
  }

  private onValueChanged(): void {
    if (!this.forms) { return; }
    const form = this.forms;
    const validators: string[] = ['required', 'pattern', 'confirm'];
    for(const field in this.formErrors) {
      this.formErrors[field] = '';
      const control = form.get(field);
      if (control && control.dirty && !control.valid) {
        const messages = this.validationMessages[field];
        for (let i = 0; i < validators.length; i++) {
          if(control.errors[validators[i]]) {
            this.formErrors[field] = messages[validators[i]];
            break;
          }
        }
      }
    }
  }

  private createForms(): void {
    this.forms = this.fb.group({
      oldPassword: ['', [ Validators.required, Validators.pattern(/^[A-Za-z0-9!@#$%^&*()_]{6,20}$/) ]],
      newPassword: ['', [ Validators.required, Validators.pattern(/^[A-Za-z0-9!@#$%^&*()_]{6,20}$/), this.confirmationValidator ]]
    });
    const valueChanges = this.forms.valueChanges.subscribe(values => {
      this.onValueChanged();
    });
    this.onValueChanged();
    this.subscriptions.push(valueChanges);
  }

  private logMessage(
    type: 'success'|'info'|'warning'|'error', 
    title: string, 
    content: string, 
    options?: object): void {
      this.notification.create(type, title, content, options);
  }

  private handleError(error: ResponseError): void {
    const title: string = error.code === 'INVALID_PASSWORD' ? '无效密码' : '错误提示';
    const message: string = error.message === 'Invalid current password' ? '输入的当前密码无效，请确认后重试！' : '修改密码失败!';
    const type: any = error.name.toLowerCase();
    this.logMessage(type, title, message);
    this.loading = false;
  }

}
